package com.nanbei.cas;

import cn.hutool.core.date.StopWatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;

/**
 * @ClassDescription: 设置点赞 50000000 次 ，观察使用 synchronized、LongAdder、AtomicLong、LongAccumulator 不同原子类锁消耗的额时间
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/10/9 15:45
 */
public class ClickDemo {
    public  static  int threadNum = 500;
    public  static  int clickNUm = 100000;
    static int num = 0;
    static AtomicLong integer =  new AtomicLong();
    static LongAdder longAdder = new LongAdder();
    static LongAccumulator longAccumulator = new LongAccumulator(Long::sum, 0);

    // 为什么 longAdder 比 AtomicLong 快
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch1 = new CountDownLatch(threadNum);
        CountDownLatch countDownLatch2 = new CountDownLatch(threadNum);
        CountDownLatch countDownLatch3 = new CountDownLatch(threadNum);
        CountDownLatch countDownLatch4 = new CountDownLatch(threadNum);


        StopWatch stopWatch = new StopWatch();
        stopWatch.start("clickBySynchronized");
        for (int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for (int j = 0; j < clickNUm; j++) {
                        clickBySynchronized();
                    }
                }finally {
                    countDownLatch1.countDown();
                }
            }).start();
        }
        countDownLatch1.await();
        stopWatch.stop();


        stopWatch.start("clickByAtomicLong");
        for (int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for (int j = 0; j < clickNUm; j++) {
                        clickByAtomicLong();
                    }
                }finally {
                    countDownLatch2.countDown();
                }
            }).start();
        }
        countDownLatch2.await();
        stopWatch.stop();

        stopWatch.start("clickByLongAdder");
        for (int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for (int j = 0; j < clickNUm; j++) {
                        clickByLongAdder();
                    }
                }finally {
                    countDownLatch3.countDown();
                }
            }).start();
        }
        countDownLatch3.await();
        stopWatch.stop();

        stopWatch.start("clickByLongAccumulator");
        for (int i = 0; i < threadNum; i++) {
            new Thread(()->{
                try {
                    for (int j = 0; j < clickNUm; j++) {
                        clickByLongAccumulator();
                    }
                }finally {
                    countDownLatch4.countDown();
                }
            }).start();
        }
        countDownLatch4.await();
        stopWatch.stop();

        System.out.println(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));

        System.out.println("--------------------");
        System.out.println("clickBySynchronized:"+num);
        System.out.println("clickByAtomicLong:"+integer.get());
        System.out.println("clickByLongAdder:"+longAdder.sum());
        System.out.println("clickByLongAccumulator:"+longAccumulator.get());


    }

    public static synchronized void clickBySynchronized(){
        num++;
    }

    public static  void clickByAtomicLong(){
        integer.getAndIncrement();
    }

    public static  void clickByLongAdder(){
        longAdder.increment();

    }

    public static  void clickByLongAccumulator(){
        longAccumulator.accumulate(1);
    }



}
